package drds.configuration.db.table_mapping;

import drds.tools.ShouldNeverHappenException;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

public class ModelBuilder {

    /**
     * 核心方法--需要控制返回数据的时候里面需要修改的字段个数为0
     */
    @SuppressWarnings({"unchecked"})
    public static final <T> List<T> build(ResultSet resultSet, Class<? extends Model> modelClass) throws Exception {
        List<T> list = new ArrayList<T>();
        ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
        int columnCount = resultSetMetaData.getColumnCount();
        String[] columnLabels = new String[columnCount + 1];
        String[] columnClassNames = new String[columnCount + 1];
        buildColumnLabelsAndTypes(resultSetMetaData, columnLabels, columnClassNames);
        while (resultSet.next()) {
            Model<?> model = null;
            try {
                model = modelClass.newInstance();
                model.clearModifiedSet();
            } catch (InstantiationException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
            Map<String, Object> map = model.copyMap();
            for (int i = 1; i <= columnCount; i++) {
                Object value;
                // 下面是基本数据处理
                /**
                 * <pre>
                 * 约定
                 * Types.INTEGER-->int
                 * Types.BIGINT-->long
                 * Types.FLOAT-->float
                 * Types.VARCHAR-->string
                 * Types.BOOLEAN-->smalint
                 * </pre>
                 */
                if (columnClassNames[i].equals(Boolean.class.getName())) {
                    value = resultSet.getBoolean(i);
                } else if (columnClassNames[i].equals(Short.class.getName())) {
                    value = resultSet.getShort(i);
                } else if (columnClassNames[i].equals(Integer.class.getName())) {
                    value = resultSet.getInt(i);
                } else if (columnClassNames[i].equals(Long.class.getName())) {
                    value = resultSet.getLong(i);
                } else if (columnClassNames[i].equals(Float.class.getName())) {
                    value = resultSet.getFloat(i);
                } else if (columnClassNames[i].equals(Double.class.getName())) {
                    value = resultSet.getDouble(i);
                } else if (columnClassNames[i].equals(String.class.getName())) {
                    value = resultSet.getString(i);
                } else if (columnClassNames[i].equals(BigDecimal.class.getName())) {
                    value = resultSet.getBigDecimal(i);
                    //
                } else if (columnClassNames[i].equals(Date.class.getName())) {
                    value = resultSet.getDate(i);
                } else if (columnClassNames[i].equals(java.sql.Date.class.getName())) {
                    value = resultSet.getDate(i);
                } else if (columnClassNames[i].equals(java.sql.Time.class.getName())) {
                    value = resultSet.getTime(i);
                } else if (columnClassNames[i].equals(java.sql.Timestamp.class.getName())) {
                    value = resultSet.getTimestamp(i);
                } else {
                    throw new ShouldNeverHappenException();
                }
                map.put(columnLabels[i], value);
            }
            model.setMap(map);
            model.clearModifiedSet();
            //统一进行更新到实体类上面的属性
            TableInfo tableInfo = ModelClassToTableInfoMap.getTableInfo(modelClass);
            Map<String, Field> fieldColumnNameToFieldMap = tableInfo.fieldColumnNameToFieldMap;
            for (Map.Entry<String, Field> entry : fieldColumnNameToFieldMap.entrySet()) {
                Field field = entry.getValue();
                field.setAccessible(true);
                field.set(model, map.get(entry.getKey()));
            }
            list.add((T) model);
        }
        return list;
    }

    /**
     * 使用引用设值方式进行注入值
     */
    private static final void buildColumnLabelsAndTypes(ResultSetMetaData resultSetMetaData, String[] columnLabels, String[] columnClassNames) throws SQLException {
        int length = columnLabels.length;
        for (int i = 1; i < length; i++) {
            columnLabels[i] = resultSetMetaData.getColumnLabel(i);
            columnClassNames[i] = resultSetMetaData.getColumnClassName(i);
        }
    }


}
